Skip to content

Refactor ConvertGenericCallExpr#145

Open
lucic71 wants to merge 2 commits into
Cpp2Rust:masterfrom
lucic71:call
Open

Refactor ConvertGenericCallExpr#145
lucic71 wants to merge 2 commits into
Cpp2Rust:masterfrom
lucic71:call

Conversation

@lucic71
Copy link
Copy Markdown
Contributor

@lucic71 lucic71 commented May 23, 2026

ConvertGenericCallExpr is a messy function and it became difficult to add new functoinality on top of it. So I decided to refactor it into: EmitCall(CollectCallInfo(expr)).

In the near future I plan to add 3 new features on top of it:

  1. Don't hoist arguments that are integer literals, they don't alias with any other argument
  2. Don't hoist if all passed arguments are local variables and all have non-reference/non-pointer types, local variables don't alias each other
  3. Translate mapped (variadic) functions that have a direct mapping in libc, for example fcntl -> libc::fcntl

In the new version of ConvertGenericCallExpr, CollectCallInfo is responsible for returning the call information:

  struct CallArg {
    enum class Kind {
      Hoisted,
      Inline,
      Materialized,
    };

    clang::Expr *expr;
    Kind kind;
    std::string param_name;
    clang::QualType param_type;
    bool has_default;
    std::string ref_temp_name;
  };

  struct CallInfo {
    clang::Expr *callee;
    bool is_variadic;
    bool is_fn_ptr_call;
    std::vector<CallArg> args;
    std::vector<clang::Expr *> variadic_args;
  };

And EmitCall is responsible for emitting the hoisted arguments, the callee and the argument list using a CallInfo.

This model makes the addition of new strategies, for example Don't hoist arguments that are integer literals, they don't alias with any other argument, easier because only the CallInfo fields have to be modified.

using Kind = CallArg::Kind;

unsigned arg_begin = 0; // skip count for operator()'s implicit object arg
CallInfo info{};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{} unneded

}
}

void Converter::EmitCall(CallInfo info) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passed by value

Materialized,
};

clang::Expr *expr;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usually these are sorted by size (larger to shorter) to reduce struct size.

std::optional<TempMaterializationCtx> ConvertCallExpr(clang::CallExpr *expr);

struct CallArg {
enum class Kind {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

: int8_t

case Kind::Hoisted:
StrCat("let",
std::format("_{}: {}", ca.param_name, ToString(ca.param_type)),
"=");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'='

bool is_variadic;
bool is_fn_ptr_call;
std::vector<CallArg> args;
std::vector<clang::Expr *> variadic_args;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's only up to one variadic arg. this can be a simple pointer initialized to null

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants